#include <iostream>
#include "ali_tokenizer.h"

using std::cout;
using std::cerr;
using std::endl;

using std::cin;

using namespace ws;

/*
 * Quick Start for using AliTokenizer interface, please follow the 7 STEPS listed below
 */

int main(int argc, char *argv[])
{
    char* conf = "/usr/local/libdata/AliWS/conf/AliTokenizer.conf";
    char* ws = "TAOBAO_CHN";
/*
    int errflag = 0;
    for (int i = 1; i < argc; i++)
    {
        if (strcmp(argv[i], "-conf") == 0)
        {
            i++;
            if(i < argc){ conf = argv[i]; } else { errflag = 1; break; }
        }
        else  if (strcmp(argv[i], "-ws") == 0)
        {
            i++ ;
            if(i < argc){ ws = argv[i]; } else { errflag = 1; break; }
        }
        else
        {
            cerr << argv[i] << endl;
            errflag = 1;
        }
    }

    if(!conf || !ws || errflag)
    {
        cerr << "Usage: " << argv[0] << " [options]" << endl;
        cerr << "Options:" << endl;
        cerr << "  configuration path:" << endl;
        cerr << "     -conf AliTokenizer_example.conf" << endl;
        cerr << "  tokenizerId: B2B_CHN; TAOBAO_CHN; INTERNET_CHN" << endl;
        cerr << "     -ws tokenizerId" << endl;
        cerr << "Example:" << endl;
        cerr << "     " << argv[0] << " -conf AliTokenizer_example.conf -ws INTERNET_CHN" << endl;
        exit(1);
    }
    */
    
//    cout << "segment text: " << endl;
    char* buf = argv[1];
    int len = strlen(buf);
//    cout << buf << endl;

    /*
     * STEP 1: Create an instance of AliTokenizerFactory
     */
    AliTokenizerFactory factory;
    
    /*
     * STEP 2: Initialize the factory with the configuration file conf.
     */
    if (!factory.Init(conf))
    {
        cerr << "load conf error"<< endl;
        exit(1);
    }

    /*
     * STEP 3: Get an AliTokenizer with tokenizerId of ws from the factory. 
     *         Note that the tokenizer you need should be enabled in configuration
     *         file, like <enable>true<enable>.
     */
    AliTokenizer* pTokenizer = factory.GetAliTokenizer(ws);
    if (!pTokenizer)
    {
        cerr << "tokenizer: " << ws << " are not loaded" << endl;
        exit(1);
    }

    /*
     * STEP 4: Create a SegResult for storing tokens
     */
    SegResult* pSegResult = pTokenizer->CreateSegResult();
    if (!pSegResult)
    {
        cerr << "create SegResult failed" << endl;
        exit(1);
    }

    /*
     * STEP 5: Segment. 
     *         SEG_TOKEN_RETRIEVE indicates fetching retrieval tokens. 
     *         SEG_TOKEN_SEMANTIC will be filled in whatever case.
     */

    int32_t ret = pTokenizer->Segment(buf, len, UTF8, SEG_TOKEN_RETRIEVE, pSegResult);
           char* result = new char[4096];
	memset(result, 0, 4096);
    /*
     * STEP 6: Access segment result 
     * There are two methods listed below to get minimum semantic token and retrieval token
     * SegResult traversal method and iterator method
     */
    if (ret == 0)//0: Segment succeed
    {
                   uint32_t seek = 0;
            result[0] = 0;
            
            SegToken* pToken = pSegResult->GetFirstToken(MAIN_LIST);
            while(pToken)
            {
                   strncpy(result + seek, pToken->pWord, pToken->length);
                   seek += pToken->length;
                   result[seek++] = 0x0002;
                   result[seek++] = 'A';
                   /*
                   if(pToken->semanticTagNum > 0)
                   {
                         for(int i = 0; i < pToken->semanticTagNum; ++i)
                         {
                               if(pToken->pSemanticTag[i].id == TAGID_BRAND)
                               {
                                     result[seek++] = 'B';
                               }
                               if(pToken->pSemanticTag[i].id == TAGID_STYLE)
                               {
                                     result[seek++] = 'S';
                               }
                               if(pToken->pSemanticTag[i].id == TAGID_CATWORD)
                               {
                                     result[seek++] = 'C';
                               }
                               if(pToken->pSemanticTag[i].id == TAGID_DESCWORD)
                               {
                                     result[seek++] = 'D';
                               }
                         }
                   }*/
                   
                   if (pToken->subTokenNum > 0)
                   {
                          SegToken* p_sub_token = NULL;
                          for (int i = 0; i < pToken->subTokenNum; ++i)
                          {
                                p_sub_token = pToken->pSubToken + i;
                                strncpy(result + seek, p_sub_token->pWord, p_sub_token->length);
                                seek += p_sub_token->length;
                                result[seek++] = 0x0002;
                                result[seek++] = 'A';
                                
                         /*       if(p_sub_token->semanticTagNum > 0)
                                {
                                       for(int i = 0; i < p_sub_token->semanticTagNum; ++i)
                                       {
                                              if(p_sub_token->pSemanticTag[i].id == TAGID_BRAND)
                                              {
                                                    result[seek++] = 'B';
                                              }
                                              if(p_sub_token->pSemanticTag[i].id == TAGID_STYLE)
                                              {
                                                    result[seek++] = 'S';
                                              }
                                              if(p_sub_token->pSemanticTag[i].id == TAGID_CATWORD)
                                              {
                                                    result[seek++] = 'C';
                                              }
                                              if(p_sub_token->pSemanticTag[i].id == TAGID_DESCWORD)
                                              {
                                                    result[seek++] = 'D';
                                              }
                                        }
                                }*/
                          }                   
                   } 
                   
                   if (pToken->relatedTokenNum > 0)
                   {
                         SegToken* p_rel_token = NULL;
                         for (int i = 0; i < pToken->relatedTokenNum; ++i)
                         {
                                p_rel_token = pToken->pRelatedToken + i;
                                strncpy(result + seek, p_rel_token->pWord, p_rel_token->length);
                                seek += p_rel_token->length;
                                result[seek++] = 0x0002;
                                result[seek++] = 'A';
                                
            /*                    if(p_rel_token->semanticTagNum > 0)
                                {
                                       for(int i = 0; i < p_rel_token->semanticTagNum; ++i)
                                       {
                                              if(p_rel_token->pSemanticTag[i].id == TAGID_BRAND)
                                              {
                                                    result[seek++] = 'B';
                                              }
                                              if(p_rel_token->pSemanticTag[i].id == TAGID_STYLE)
                                              {
                                                    result[seek++] = 'S';
                                              }
                                              if(p_rel_token->pSemanticTag[i].id == TAGID_CATWORD)
                                              {
                                                    result[seek++] = 'C';
                                              }
                                              if(p_rel_token->pSemanticTag[i].id == TAGID_DESCWORD)
                                              {
                                                    result[seek++] = 'D';
                                              }
                                        }
                                }*/
                         }
                   }

                  pToken = pToken->pRightSibling;                
            }
            
            result[seek] = '\0';
        }         
/*        string res;
        SegToken* pToken = NULL;

        //6.1 get semantic token 
        cout << "get semantic token: " << endl;
        pToken= pSegResult->GetFirstToken(MAIN_LIST);
        while (pToken)
        {
            res += string((const char*)pToken->pWord, pToken->length);
            res += " ";
            pToken = pToken->pRightSibling;
        }
        cout << res << endl;
        res = "";

        //6.2 get minimum semantic token using SegResult traversal method
        cout << "get minimum semantic token using SegResult traversal method: " << endl;
        pToken = pSegResult->GetFirstToken(MAIN_LIST);
        while (pToken)
        {
            //pToken is minimum semantic token
            if (pToken->subTokenNum <= 0 || !IsSemanticToken(pToken->pSubToken->tokenType))
            {
                res += string((const char*)pToken->pWord, pToken->length);
                res += " ";
            }
            //pToken is semantic token, get its children as minimum semantic tokens
            else
            {
                for (int i = 0; i < pToken->subTokenNum; ++i)
                {
                    SegToken* pSubToken = pToken->pSubToken + i;
                    res += string((const char*)pSubToken->pWord, pSubToken->length);
                    res += " ";
                }
            }
            pToken = pToken->pRightSibling;
        }
        cout << res << endl;
        res = "";
        
        //6.3 get retrieval token using SegResult traversal method
        cout << "get retrieval token using SegResult traversal method: " << endl;
        pToken = pSegResult->GetFirstToken(MAIN_LIST);
        while (pToken)
        {
            if (IsRetrieveToken(pToken->tokenType))
            {
                res += string((const char*)pToken->pWord, pToken->length);
                res += " ";
            }
            else
            {
                for (int i = 0; i < pToken->subTokenNum; ++i)
                {
                    SegToken* pSubToken = pToken->pSubToken + i;
                    if (IsRetrieveToken(pSubToken->tokenType))
                    {
                        res += string((const char*)pSubToken->pWord, pSubToken->length);
                        res += " ";
                    }
                    else
                    {
                        for (int j = 0; j < pSubToken->subTokenNum; ++j)
                        {
                            SegToken* pSubToken_2 =  pSubToken->pSubToken + j;
                            res += string((const char*)pSubToken_2->pWord, pSubToken_2->length);
                            res += " ";
                        }
                    }

                    //get SEG_TOKEN_RETRIEVE_EXTEND token
                    for (int k = 0; k < pSubToken->relatedTokenNum; ++k)
                    {
                        SegToken* pRelatedToken = pSubToken->pRelatedToken + k;
                        res += "#";
                        res += string(pRelatedToken->pWord, pRelatedToken->length);
                        res += " ";
                    }
                }
            }

            //get SEG_TOKEN_RETRIEVE_EXTEND token
            for (int i = 0; i < pToken->relatedTokenNum; ++i)
            {
                SegToken* pRelatedToken = pToken->pRelatedToken + i;
                res += "#";
                res += string(pRelatedToken->pWord, pRelatedToken->length);
                res += " ";
            }

            pToken = pToken->pRightSibling;
        }
        cout << res << endl;
        res = "";

        //6.4 get minimum semantic token using iterator method
        cout << "get minimum semantic token using iterator method: " << endl;
        for (SegResult::Iterator iter = pSegResult->Begin(SEMANTIC_ITERATOR);
             iter != pSegResult->End(SEMANTIC_ITERATOR); ++iter)
        {
            res += string((const char*)iter->pWord, iter->length);
            res += " ";
        }
        cout << res << endl;
        res = "";

        //6.5 get retrieval token using iterator method
        cout << "get retrieval token using iterator method: " << endl;
        for (SegResult::Iterator iter = pSegResult->Begin(RETRIEVE_ITERATOR);
             iter != pSegResult->End(RETRIEVE_ITERATOR); ++iter)
        {
            if (IsExtendRetrieveToken(iter->tokenType))
                res += "#";
            res += string((const char*)iter->pWord, iter->length);
            res += " ";
        }
        cout << res << endl;
        res = "";

        //6.6 get cross semantic retrieval token
        cout << "get cross semantic retrieval token: " << endl;
        pToken = pSegResult->GetFirstToken(ACCESSORY_LIST);
        while (pToken)
        {
            res += string((const char*)pToken->pWord, pToken->length);
            res += " ";
            pToken = pToken->pRightSibling;
        }
        cout << res << endl;
        res = "";
    }*/
    else
    {
        cerr << "segment failed" << endl;
    }
//    delete[] result;
    cout<<result<<endl;
    delete[] result;
    /*
     * STEP 7: Release SegResult
     */
    pTokenizer->ReleaseSegResult(pSegResult);

    return 0;
}


